package cn.yx.tool.message.service;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import cn.yx.common.core.constant.SeparatorConstant;
import cn.yx.common.core.util.StringUtil;
import cn.yx.common.core.util.io.FileUtil;
import cn.yx.common.core.util.io.IoUtil;
import cn.yx.tool.message.pojo.MessageKey;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * <p>国际化消息Key常量类生成服务</p>
 *
 * @author Wgssmart
 */
@Service
@Slf4j
public class MessageKeyClassGeneratorService {

    /**
     * 从指定的Java文件中读取抛出的CommonException或AppException生成message key对应的class类
     *
     * @param javaFilePath
     */
    public void generateMessageKeyClass(String javaFilePath) {
        List<MessageKey> messageKeyList = getMessageKey(javaFilePath);
        if (CollectionUtil.isNotEmpty(messageKeyList)) {
            writeMessageKeyClass(javaFilePath, messageKeyList);
        }
    }

    /**
     * 从指定的多个Java文件中读取抛出的CommonException或AppException生成message key对应的class类
     *
     * @param javaFilePathList
     */
    public void generateMessageKeyClasses(List<String> javaFilePathList) {
        for (String javaFilePath : javaFilePathList) {
            generateMessageKeyClass(javaFilePath);
        }
    }

    /**
     * 指定根目录，从该目录下Java文件中抛出的CommonException或AppException生成message key对应的class类
     *
     * @param rootPath
     */
    public void generateMessageKeyClassesFromRootPath(String rootPath) {
        List<File> files = cn.hutool.core.io.FileUtil.loopFiles(rootPath);
        for (File file : files) {
            String path = file.getAbsolutePath();
            if (path.endsWith(".java")) {
                generateMessageKeyClass(path);
            }
        }
    }

    /**
     * 指定根目录，从该目录下Java文件中抛出的CommonException或AppException生成message key对应的class类
     *
     * @param rootPathList
     */
    public void generateMessageKeyClassesFromRootPath(List<String> rootPathList) {
        for (String rootPath : rootPathList) {
            List<File> files = cn.hutool.core.io.FileUtil.loopFiles(rootPath);
            for (File file : files) {
                String path = file.getAbsolutePath();
                if (path.endsWith(".java")) {
                    generateMessageKeyClass(path);
                }
            }
        }
    }

    /**
     * 解析Java文件，获取message key
     *
     * @param javaFilePath
     * @return
     */
    private List<MessageKey> getMessageKey(String javaFilePath) {
        List<MessageKey> messageKeyList = new ArrayList<>();
        try (BufferedReader bufferedReader = new BufferedReader(
                new InputStreamReader(
                        new FileInputStream(javaFilePath)))) {
            String line;
            String english = "";
            String simplifiedChinese = "";
            while (Objects.nonNull(line = bufferedReader.readLine())) {
                if (line.contains("// @English")) {
                    String[] strArray = line.split(SeparatorConstant.EQUAL);
                    english = strArray[1].trim();
                }
                if (line.contains("// @SimplifiedChinese")) {
                    String[] strArray = line.split(SeparatorConstant.EQUAL);
                    simplifiedChinese = strArray[1].trim();
                }
                if (line.contains("throw new CommonException(\"") || line.contains("throw new AppException(\"")) {
                    String key = line.trim().replace("throw new CommonException(\"", StringUtil.EMPTY_STRING)
                            .replace("throw new AppException(\"", StringUtil.EMPTY_STRING)
                            .replace("\", e);", StringUtil.EMPTY_STRING)
                            .replace("\");", StringUtil.EMPTY_STRING);
                    if (!messageKeyList.stream().map(MessageKey::getKey).collect(Collectors.toList()).contains(key)) {
                        MessageKey messageKey = new MessageKey();
                        messageKey.setKey(key);
                        messageKey.setEnglish(english);
                        messageKey.setSimplifiedChinese(simplifiedChinese);
                        messageKeyList.add(messageKey);
                    } else {
                        MessageKey messageKey = messageKeyList.stream().filter(mk -> key.equals(mk.getKey())).findFirst().orElse(new MessageKey());
                        if (StrUtil.isNotEmpty(english) && StrUtil.isEmpty(messageKey.getEnglish())) {
                            messageKey.setEnglish(english);
                        }
                        if (StrUtil.isNotEmpty(simplifiedChinese) && StrUtil.isEmpty(messageKey.getSimplifiedChinese())) {
                            messageKey.setSimplifiedChinese(simplifiedChinese);
                        }
                    }
                }
            }
        } catch (IOException e) {
            log.error("read java file error, path: {}", javaFilePath, e);
        }
        return messageKeyList;
    }

    /**
     * 写出MessageKey类到指定文件
     *
     * @param messageKeyList
     */
    private void writeMessageKeyClass(String javaFilePath, List<MessageKey> messageKeyList) {
        String separator = javaFilePath.contains(SeparatorConstant.SLASH) ?
                SeparatorConstant.SLASH : SeparatorConstant.BACK_SLASH;
        String utilClassName = javaFilePath.substring(javaFilePath.lastIndexOf(separator) + 1)
                .replace(".java", StringUtil.EMPTY_STRING);
        String messageKeyClassName = utilClassName + "MessageKey";
        StringBuilder text = new StringBuilder("import cn.yx.common.core.annotation.message.English;\n");
        text.append("import cn.yx.common.core.annotation.message.I18nMessage;\n")
                .append("import cn.yx.common.core.annotation.message.SimplifiedChinese;\n")
                .append("\n")
                .append("/**\n")
                .append(" * <p>").append(utilClassName).append(" Key</p>\n")
                .append(" *\n")
                .append(" * @author Wgssmart\n")
                .append(" */\n")
                .append("@I18nMessage\n")
                .append("public final class ").append(messageKeyClassName).append(" {\n")
                .append("\n")
                .append("\tprivate ").append(messageKeyClassName).append("() {}\n")
                .append("\n");
        for (MessageKey messageKey : messageKeyList) {
            text.append("\t@SimplifiedChinese(\"").append(messageKey.getSimplifiedChinese()).append("\")\n")
                    .append("\t@English(\"").append(messageKey.getEnglish()).append("\")\n")
                    .append("\tpublic static final String ").append(getMessageKeyFieldName(messageKey.getKey()))
                    .append(" = \"").append(messageKey.getKey()).append("\";\n")
                    .append("\n");
        }
        text.append("}");
        FileUtil.mkdirs("message-key");
        IoUtil.writeText(text.toString(), "message-key" + SeparatorConstant.SLASH + messageKeyClassName + ".java");
    }

    private String getMessageKeyFieldName(String messageKey) {
        String key = messageKey.substring(messageKey.lastIndexOf(SeparatorConstant.DOT) + 1);
        return StringUtil.camelToUnderline(key).toUpperCase();
    }

}
